# config_loader.py
import sys
import os

from dotenv import load_dotenv

from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session

from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import logging

from models.comment_schema import RawComment, VideoSource       
from datetime import datetime
import time
from pprint import pprint

from utils.youtube_client import get_youtube_service



# 获取当前文件所在目录的上层目录（即 src/）
current_dir = os.path.dirname(os.path.abspath(__file__))
src_dir = os.path.join(current_dir, '..')
sys.path.append(src_dir)

# 现在可以正常导入 models 模块了
from models.comment_schema import RawComment, VideoSource

# 禁用 Google API 的 file_cache 警告
import warnings
warnings.filterwarnings("ignore", message="file_cache is only supported with oauth2client<4.0.0")

logger = logging.getLogger(__name__)



class Config:
    def __init__(self):
        load_dotenv()
        self.API_KEY = os.getenv("YT_API_KEY")
        self.DB_CONFIG = {
            'host': os.getenv("DB_HOST"),
            'user': os.getenv("DB_USER"),
            'password': os.getenv("DB_PASS")
        }


Base = declarative_base()


def get_youtube_service(api_key):
    """
    创建 YouTube API 客户端
    :param api_key: YouTube API Key
    :return: YouTube 客户端对象
    """
    return build('youtube', 'v3', developerKey=api_key)

class YouTubeComment(Base):
    __tablename__ = 'comments'
    id = Column(Integer, primary_key=True)
    video_id = Column(String(50))
    author = Column(String(100))
    comment_text = Column(String(1000))
    # 其他字段...


class CommentCollector:
    def __init__(self, api_key):
        self.api_key = api_key
        self.youtube = build('youtube', 'v3', developerKey=api_key)

    def get_comments(self, video_info, max_comments_per_video=500):
        """
        获取单个视频的评论（支持分页）
        :param video_info: 包含 id 和 video_id 的字典
        :param max_comments_per_video: 最大评论数
        :return: RawComment 列表
        """
        video_id = video_info["video_id"]
        comments = []
        next_page_token = None
        
        while len(comments) < max_comments_per_video:
            remaining = max_comments_per_video - len(comments)
            fetch_count = min(100, remaining)
            
            params = {
                "part": "snippet,replies",
                "videoId": video_id,
                "maxResults": fetch_count,
                "pageToken": next_page_token,
                "order": "relevance"
            }

            try:
                response = self.youtube.commentThreads().list(**params).execute()
            except HttpError as e:
                logging.warning(f"获取视频 {video_id} 评论失败: {str(e)}")
                time.sleep(5)
                continue

            items = response.get("items", [])
            if not items:
                logging.info(f"视频 {video_id} 已无更多评论")
                break

            for item in items:
                snippet = item["snippet"]["topLevelComment"]["snippet"]
                
                # ✅ 正确保存主评论的原始 ID
                main_comment = RawComment(
                    author=snippet["authorDisplayName"],
                    video_id=video_id,
                    comment_text=snippet["textOriginal"],
                    published_at=datetime.strptime(snippet["publishedAt"], "%Y-%m-%dT%H:%M:%SZ"),
                    like_count=snippet.get("likeCount", 0),
                    video_source_id=video_info["id"],
                    
                    # ✅ 设置主评论的原始 ID
                    top_comment_id=item["snippet"]["topLevelComment"]["id"],
                    # ✅ 主评论的 parent_id 为 NULL
                    parent_id=None
                )

                comments.append(main_comment)

            next_page_token = response.get("nextPageToken")
            if not next_page_token:
                break

        logging.info(f"已抓取 {len(comments)} 条评论 from 视频 {video_id}")
        return comments       


    def get_comments_for_videos(self, video_sources, max_comments_per_video=500):
        """
        获取多个视频的评论
        :param video_sources: 视频源信息列表（每个元素为包含 id 和 video_id 的字典）
        :param max_comments_per_video: 每个视频最大抓取数量
        :return: 所有评论的列表
        """
        all_comments = []
        for video_info in video_sources:
            logging.info(f"正在抓取视频 {video_info['video_id']} 的评论...")
            comments = self.get_comments(video_info, max_comments_per_video)
            all_comments.extend(comments)
            logging.info(f"已抓取 {len(comments)} 条评论")
        
        return all_comments
    




def fetch_youtube_replies(db: Session, video_id: str):
    """
    只采集子评论，主评论必须已存在
    :param db: 数据库会话（外部传入）
    :param video_id: 视频ID
    """
    try:
        # youtube = build('youtube', 'v3', developerKey=os.getenv("YT_API_KEY"), cache_discovery=False)
        youtube = get_youtube_service(timeout=60)  # 自动使用下一个 Key
    except Exception as e:
        logger.error(f"❌ 创建 YouTube API 客户端失败: {str(e)}")
        return

    next_page_token = None
    total_comments_collected = 0
    retry_count = 0
    max_retries = 3

    while retry_count < max_retries:
        try:
            response = youtube.commentThreads().list(
                part="snippet,replies",
                videoId=video_id,
                maxResults=100,
                pageToken=next_page_token,
                textFormat="plainText"
            ).execute()

            items = response.get('items', [])
            logger.info(f"🔍 当前页面共 {len(items)} 条主评论")

            if not items:
                logger.info("🔚 没有更多主评论")
                break

            for item in items:
                # 主评论信息
                top_level_comment = item['snippet']['topLevelComment']
                api_top_id = item['id']

                # 使用新 Session 查询主评论是否存在
                with db.bind.connect() as conn:  # 使用绑定连接
                    main_comment = db.query(RawComment).filter_by(top_comment_id=api_top_id).with_session(db).first()

                if not main_comment:
                    logger.warning(f"⚠️ 主评论 {api_top_id} 不存在，尝试通过API直接获取主评论...")

                    # 尝试通过API获取主评论信息
                    try:
                        top_comment_response = youtube.comments().list(
                            part="snippet",
                            id=api_top_id,
                            textFormat="plainText"
                        ).execute()

                        if top_comment_response.get('items'):
                            top_comment_data = top_comment_response['items'][0]['snippet']
                            logger.info(f"📥 新发现主评论 {api_top_id}，正在补充采集")

                            # 创建新的主评论
                            main_comment = RawComment(
                                author=top_comment_data["authorDisplayName"],
                                video_id=video_id,
                                comment_text=top_comment_data["textOriginal"],
                                published_at=datetime.fromisoformat(top_comment_data["publishedAt"].replace("Z", "+00:00")),
                                like_count=top_comment_data.get("likeCount", 0),
                                parent_id=None,
                                top_comment_id=api_top_id
                            )

                            # 获取视频源信息
                            video_source = db.query(VideoSource).filter_by(video_id=video_id).first()
                            if video_source:
                                main_comment.video_source_id = video_source.id

                            db.add(main_comment)
                            db.commit()
                            logger.info(f"✅ 补充采集主评论 {api_top_id}")
                        else:
                            logger.warning(f"⚠️ 无法获取主评论 {api_top_id} 的详细信息")
                            continue
                    except Exception as e:
                        logger.error(f"❌ 获取主评论 {api_top_id} 详情失败: {str(e)}")
                        continue

                replies = item.get('replies', {}).get('comments', [])
                logger.info(f"🔁 发现主评论 {api_top_id} 有 {len(replies)} 条子评论")

                for reply in replies:
                    reply_id = reply['id']
                    reply_snippet = reply['snippet']

                    existing = db.query(RawComment).filter_by(top_comment_id=reply_id).first()
                    if existing:
                        logger.debug(f"🔁 子评论 {reply_id} 已存在，跳过")
                        continue

                    # 获取主评论的文本内容作为 parent_text
                    parent_text = top_level_comment['snippet']['textOriginal']

                    comment = RawComment(
                        video_id=video_id,
                        author=reply_snippet['authorDisplayName'],
                        published_at=datetime.fromisoformat(reply_snippet['publishedAt'].replace("Z", "+00:00")),
                        like_count=reply_snippet['likeCount'],
                        comment_text=reply_snippet['textOriginal'],
                        parent_id=api_top_id,
                        parent_text=parent_text,
                        is_analyzed=False,
                        video_source_id=main_comment.video_source_id,
                        top_comment_id=reply_id
                    )

                    db.add(comment)
                    total_comments_collected += 1
                    logger.info(f"✅ 插入子评论 {reply_id}")

                db.commit()

            next_page_token = response.get('nextPageToken')
            if not next_page_token:
                break

        except HttpError as e:
            logger.error(f"❌ YouTube API 请求失败: {str(e)}")
            retry_count += 1
            logger.info(f"🔄 正在第 {retry_count} 次重试...")
            time.sleep(5)
            continue

        except Exception as e:
            logger.error(f"🚨 意外错误: {str(e)}", exc_info=True)
            db.rollback()  # 回滚事务
            retry_count += 1
            logger.info(f"🔄 正在第 {retry_count} 次重试...")
            time.sleep(5)
            continue

        retry_count = 0  # 重置重试计数器

    logger.info(f"✅ 共采集 {total_comments_collected} 条子评论")